using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using Sedna.Core.Controller;
using Sedna.Core.Controller.Configurations;
using Sedna.Core.Controls.Support.Javascript;
using Sedna.Core.DataBinding;
using Sedna.Core.Tiles.Contents;
using DataBinder = Sedna.Core.DataBinding.DataBinder;

namespace Sedna.Core.Controls.Support
{
	public abstract class BaseControl : WebControl, IContent, IConfigurationAware, IControlDataLoadAware
	{
		protected IConfiguration configuration;
		protected string configurationId;
		protected IDataBinder binder;
        protected bool clientScriptingEnabled = false;
        protected string clientVariable = null;
        protected string javascriptClass;

        private String contentPlaceHolderId;

        #region Javascript support
	   
	    public virtual bool ClientScriptingEnabled
		{
            get { return clientScriptingEnabled /*|| clientVariable != null*/; }
			set { clientScriptingEnabled = value; }
		}

		public virtual string ClientVariable
		{
            get { return ControlUtil.GetClientVariable(this, clientVariable)/*clientVariable*/; }
			set { clientVariable = value; }
		}
	    
	    
	    public virtual string NodeName
	    {
            get { return ClientID; }
	    }
	    
	    public virtual string JavascriptClass
	    {
            get { return javascriptClass; }
            set { javascriptClass = value;  }
        }


        protected virtual void RenderScriptAttributes(HtmlTextWriter writer)
        {
            foreach (DictionaryEntry entry in BuildScriptParameters())
            {
                writer.AddAttribute("sedna:" + (string)entry.Key, (string)entry.Value);
            }
        }

        protected virtual void DeclareScriptVariable()
        {
            ControlUtil.EnsureIdAttribute(this);
            JavascriptController.Current.DeclareClass(JavascriptClass);
            if (ClientVariable != null)
            {
                JavascriptController.Current.DeclareObjectByNode(ClientVariable, JavascriptClass, NodeName);
            }
        }
	    
        protected virtual IDictionary BuildScriptParameters()
        {
            IDictionary parameters = new ListDictionary();
            parameters.Add("jsClass", JavascriptClass);
            return parameters;
        }

        #endregion
	    
	    public String ContentPlaceHolderId
		{
			get { return contentPlaceHolderId;}
			set { contentPlaceHolderId = value;}
		}

		public virtual IConfiguration Configuration
		{
			get{return configuration;}
			set{this.configuration = value;}
		}

		[Bindable(true), Category("Sedna"), DefaultValue("configuration.default.BaseControl")]
		public virtual string ConfigurationId
		{
			get { return configurationId; }
			set { this.configurationId = value; }
		}

		public BaseControl()
		{
		}

		public BaseControl(IConfiguration configuration): this()
		{
			this.configuration = configuration;
			configurationId = configuration.ObjectName;
            BuildFromConfiguration();
		}


		protected override void OnInit(EventArgs e)
		{
			if (configuration == null) {
				configuration = (IConfiguration)SpringContextFactory.GetContext().GetObject(configurationId);
                BuildFromConfiguration();                
			}
            Build();
			binder=new DataBinder(this, configuration, ExecutionContext.GetCurrent(ClientID));
			base.OnInit (e);
		}
	   
        //todo: non-virtual?
	    protected void BuildFromConfiguration()
	    {
            ID = configuration.Id;

            if (configuration.CssClass != null)
            {
                this.CssClass = configuration.CssClass;
            }
            IClientScriptingConfiguration clientScriptingConfiguration = Configuration as IClientScriptingConfiguration;
            if (clientScriptingConfiguration != null)
            {
                javascriptClass = clientScriptingConfiguration.JavascriptClass;
                ClientVariable = clientScriptingConfiguration.ClientVariable;
                ClientScriptingEnabled = clientScriptingConfiguration.ClientScriptingEnabled;
            }


            EnsureSecurity();
	        
            ControlUtil.SetupClientAttributes(this, configuration);	        	        
	    }

		protected virtual void Build()
		{            
		}

		protected virtual void EnsureSecurity()
		{
            this.Visible = configuration.IsVisibleForPrincipal() && configuration.Visible;
			this.Enabled = configuration.IsEnabledForPrincipal() && configuration.Enabled;

			//This is done by ASP.NET
/*
			foreach(Control control in this.Controls)
			{
				control.Visible = this.Visible;
				WebControl webControl = control as WebControl;
				if(webControl != null)
				{
					webControl.Enabled = this.Enabled;
				}
			}
*/
			
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
			Unbind();
			ControlUtil.ExecuteOnLoad(ExecutionContext.GetCurrent(ClientID), Context, Configuration, this.ClientID);

            //if (Configuration.VisibleBindPath != null)
            //    Visible = true; // To reach the OnPreRender method and analyze visibility in the Bind method
		}

		public virtual void OnDataLoad()
		{
			ControlUtil.ExecuteOnDataLoad(ExecutionContext.GetCurrent(ClientID),Context, Configuration, this.ClientID);
		}

		protected override void OnPreRender(EventArgs e)
		{
			base.OnPreRender(e);
			ControlUtil.ExecuteOnPreRender(ExecutionContext.GetCurrent(ClientID), Context, Configuration, this.ClientID);
			Bind();		    
		}


	    protected override void AddAttributesToRender(HtmlTextWriter writer)
	    {
	        base.AddAttributesToRender(writer);
	        if (ClientScriptingEnabled)
	        {
	            RenderScriptAttributes(writer);
	        }
	    }	    

		protected virtual void Bind()
		{
            //Visible = Configuration.Visible;

            //binder.Bind("Enabled");
            //binder.Bind("Visible");

            //Enabled = Enabled && Configuration.IsEnabledForPrincipal();
            //Visible = Visible && Configuration.IsVisibleForPrincipal();
		}

        protected virtual void Unbind()
        {
            //binder.Unbind("Enabled");
            //binder.Unbind("Visible");
        }

	}
}
